﻿using System;
using System.Collections.Generic;

using System.Text;
using System.Collections;
using AuroraLightsFX.Properties;
using System.Globalization;
using System.Drawing;

namespace AuroraLightsFX
{

    public class GroupPacket
    {
        // Fields
        private ArrayList _GroupActionsInfoCommands = new ArrayList();
        private uint REPORT_LENGTH = 9;

        // Methods
        public GroupPacket(PacketData ledsGroup)
        {
            if ((ledsGroup == null) || ledsGroup.IsEmpty())
            {
                throw new GroupPacketException(Resources.InvalidGroupError);
            }
            if ((ledsGroup.Actions == null) || (ledsGroup.Actions.Length <= 0))
            {
                throw new GroupPacketException(Resources.MissingActionsError);
            }
            byte[] ledsInfo = new byte[3];
            this.FillLedsBytes(ledsInfo, ledsGroup);
            foreach (ThemeDataset.ActionsRow row in ledsGroup.Actions)
            {
                byte[] infoCommand = new byte[this.REPORT_LENGTH];
                infoCommand[0] = 0;
                infoCommand[2] = (byte)ledsGroup.ZoneID;
                infoCommand[3] = ledsInfo[0];
                infoCommand[4] = ledsInfo[1];
                infoCommand[5] = ledsInfo[2];
                this.FillActionsBytes(infoCommand, row);
                this._GroupActionsInfoCommands.Add(infoCommand);
            }
            if (ledsGroup.Loop)
            {
                byte[] buffer3 = this.CreateLoopInfoCommand();
                buffer3[2] = 0;
                this._GroupActionsInfoCommands.Add(buffer3);
            }
        }

        private long ConvertHexToInt(string hexNumber)
        {
            return long.Parse(hexNumber, NumberStyles.HexNumber);
        }

        private byte[] CreateLoopInfoCommand()
        {
            byte[] buffer = new byte[this.REPORT_LENGTH];
            buffer[0] = 0;
            buffer[1] = 4;
            return buffer;
        }

        private string DepureResult(string ledsString)
        {
            string str = "";
            string[] strArray = ledsString.Split(new char[] { ',' });
            foreach (string str2 in strArray)
            {
                if (str2.IndexOf('-') != -1)
                {
                    string[] strArray2 = str2.Split(new char[] { '-' });
                    int num = Convert.ToByte(strArray2[1]) - Convert.ToByte(strArray2[0]);
                    if (num > 1)
                    {
                        str = str + str2 + ",";
                    }
                    else
                    {
                        string str4 = str;
                        str = str4 + strArray2[0] + "," + strArray2[1] + ",";
                    }
                }
                else
                {
                    str = str + str2 + ",";
                }
            }
            if (str.EndsWith(","))
            {
                str = str.Substring(0, str.Length - 1);
            }
            return str;
        }

        private void FillActionsBytes(byte[] InfoCommand, ThemeDataset.ActionsRow actionRow)
        {
            if (actionRow != null)
            {
                byte num;
                byte num2;
                byte num3;
                InfoCommand[1] = (byte)actionRow.ActionTypeID;
                InfoCommand[2] = (byte)(InfoCommand[2] | ((actionRow.Duration == 1) ? 0x80 : 0));
                byte b = 0;
                GetColorComponents(actionRow.Color1, out num, out num2, out num3, out b);
                Color color = Color.FromArgb(num, num2, num3, b);
                GetColorComponents(actionRow.Color2, out num, out num2, out num3, out b);
                Color color2 = Color.FromArgb(num, num2, num3, b);
                InfoCommand[6] = (byte)(color.R & 240);
                InfoCommand[6] = (byte)(InfoCommand[6] | ((byte)((color.G & 240) >> 4)));
                InfoCommand[7] = (byte)(color.B & 240);
                InfoCommand[7] = (byte)(InfoCommand[7] | ((byte)((color2.R & 240) >> 4)));
                InfoCommand[8] = (byte)(color2.G & 240);
                InfoCommand[8] = (byte)(InfoCommand[8] | ((byte)((color2.B & 240) >> 4)));
            }
        }

        private void FillLedsBytes(byte[] ledsInfo, PacketData ledsGroup)
        {
            int num = 0;
            if ((ledsGroup == null) || ledsGroup.IsEmpty())
            {
                throw new GroupPacketException(Resources.MissingLedsError);
            }
            ArrayList list = new ArrayList();
            foreach (Led led in ledsGroup.Leds)
            {
                num |= ((int)1) << led.LedID;
            }
            ledsInfo[0] = (byte)((num & 0xf0000) >> 0x10);
            ledsInfo[1] = (byte)((num & 0xff00) >> 8);
            ledsInfo[2] = (byte)(num & 0xff);
        }

        private static void GetColorComponents(string hexNumber, out byte a, out byte r, out byte g, out byte b)
        {
            int num = int.Parse(hexNumber.Replace("#", ""), NumberStyles.HexNumber);
            a = (byte)((num & 0xff000000L) >> 0x18);
            r = (byte)((num & 0xff0000) >> 0x10);
            g = (byte)((num & 0xff00) >> 8);
            b = (byte)(num & 0xff);
        }

        private string GetLedsString(int leds)
        {
            string ledsString = "";
            int num = -1;
            for (byte i = 0; i < 0x20; i = (byte)(i + 1))
            {
                if ((leds & (((int)1) << i)) != 0)
                {
                    if (ledsString.Length == 0)
                    {
                        ledsString = i.ToString();
                        num = i;
                    }
                    else if ((i - num) == 1)
                    {
                        if (!ledsString.EndsWith("-"))
                        {
                            ledsString = ledsString + "-";
                        }
                        num = i;
                    }
                    else
                    {
                        if (!ledsString.EndsWith("-"))
                        {
                            ledsString = ledsString + ",";
                        }
                        num = i;
                        ledsString = ledsString + num.ToString();
                    }
                }
                else if (ledsString.EndsWith("-"))
                {
                    ledsString = ledsString + num.ToString();
                }
            }
            if ((num != -1) && ledsString.EndsWith("-"))
            {
                ledsString = ledsString + num.ToString();
            }
            return this.DepureResult(ledsString);
        }

        public override string ToString()
        {
            string str = "";
            foreach (byte[] buffer in this._GroupActionsInfoCommands)
            {
                int num = buffer[2] & 15;
                str = str + string.Format("Byte 0 --> Action: {0}\r", ((ActionEnum)buffer[1]).ToString());
                str = str + string.Format("Byte 1 --> Duration: {0} \t\t\tGroup: {1}\r", (((buffer[2] >> 7) & 1) == 0) ? "Short" : "Long", (num > 0) ? num.ToString() : "-");
                int leds = ((buffer[3] << 0x10) | (buffer[4] << 8)) | buffer[5];
                str = str + string.Format("Bytes 2-4 --> Leds: {0}\r", this.GetLedsString(leds));
                byte num3 = (byte)((buffer[6] & 240) >> 4);
                byte num4 = (byte)(buffer[6] & 15);
                byte num5 = (byte)((buffer[7] & 240) >> 4);
                byte num6 = (byte)(buffer[7] & 15);
                byte num7 = (byte)((buffer[8] & 240) >> 4);
                byte num8 = (byte)(buffer[8] & 15);
                str = str + string.Format("Bytes 5-7 --> Initial color: r({0:X}),g({1:X}),b({2:X}) \tFinal color: r({3:X}),g({4:X}),b({5:X})\r", new object[] { num3, num4, num5, num6, num7, num8 });
                str = str + "\r";
                str = str + string.Format("Command: {0:X2} {1:X2} {2:X2} {3:X2} {4:X2} {5:X2} {6:X2} {7:X2}", new object[] { buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8] });
                str = str + "\r\r";
            }
            return str;
        }

        // Properties
        public ArrayList GroupActionsInfoCommands
        {
            get
            {
                return this._GroupActionsInfoCommands;
            }
        }

        // Nested Types
        public enum ActionEnum : byte
        {
            Loop = 4,
            Morph = 1,
            PlayPowerStatus = 15,
            Pulse = 2,
            SetColor = 3
        }

        public enum DurationEnum : byte
        {
            Long = 1,
            Short = 0
        }
    }

}
